/**
 * WebHttpResponse.js
 * @author Ulyan Sobin
 * @description WebHttpResponse class
 */

"use strict";

const http = require("http");
const { WebResponse } = require("../WebResponse");
const cookie = require("../../cookie");
const { cube_info } = require("../../index");

const CONSTANT_HEAD = {
	"Server": `${cube_info.name}/${cube_info.version}`
};

class WebHttpResponse extends WebResponse {
	
	/** @type {http.ServerResponse} */
	origin;

	/** @type {boolean} */
	pressed;

	/**
	 * Constructor of `WebHttpResponse`
	 * @param {http.ServerResponse} response 
	 */
	constructor (response) {
		super();
		this.origin = response;
		this.pressed = false;
	}

	/**
	 * Press response data at once
	 * @param {number} status 
	 * @param {object} head
	 * @param {any} body 
	 */
	press(status, head, body) {
		if (this.pressed) return;
		if (this.cookie && (this.cookie instanceof cookie.CookieSet)
			&& this.cookie.length() > 0)
			head["Set-Cookie"] = this.cookie.publish();
		head = Object.assign(head, CONSTANT_HEAD);
		this.origin.writeHead(status, head);
		this.origin.write(Buffer.from(body));
		this.origin.end();
		this.pressed = true;
	}

	/**
	 * Send response data from a `ReadableStream`
	 * @param {number} status 
	 * @param {object} head 
	 * @param {ReadableStream} istream 
	 */
	from(status, head, istream) {
		if (this.pressed) return;
		if (this.cookie && (this.cookie instanceof cookie.CookieSet)
			&& this.cookie.length() > 0)
			head["Set-Cookie"] = this.cookie.publish();
		head = Object.assign(head, CONSTANT_HEAD);
		this.origin.writeHead(status, head);
		this.pressed = true;
		istream.pipe(this.origin);
	}

	/**
	 * Press response data as plain text
	 * @param {number} status
	 * @param {string} text
	 * @param {string} charset
	 */
	pressText(status, text, charset) {
		if (charset == undefined) charset = "utf-8";
		this.press(status, { "Content-Type": `text/plain; charset=${charset}` }, text);
	}

	/**
	 * Press response data as JSON
	 * @param {any|string} json
	 * @param {?number} status
	 */
	pressJSON(json, status) {
		let code = typeof(status) == "number" ? status : 200;
		let body;
		if (typeof(json) != "string") body = JSON.stringify(json);
		else body = json;
		this.pressText(code, body);
	}

}

module.exports.WebHttpResponse = WebHttpResponse;